#include<iostream>
#include<vector>
#include<signal.h>
#include<unistd.h>

#define BLOCK_SIGNAL 2
#define MAX_SIGNUM 31

using namespace std;

static vector<int> sigarr = {2,3};

static void show_pending(const sigset_t& pending)
{
    for(int signo = 1; signo <= MAX_SIGNUM; ++signo)
    {
        if(sigismember(&pending,signo))
        {
            cout << "1";
        }
        else cout << "0";
    }
    cout << endl;
}

static void myhandler(int signo)
{
    cout << signo << " 信号已经被递达！"  << endl;
}

int main()
{
    for(const auto& signo : sigarr)
    {
        signal(signo,myhandler);
    }
    // 1.先尝试屏蔽指定的信号
    sigset_t block, oblock, pending;//oblock：输出型参数，表示旧的屏蔽字   sigset_t：信号集,这个类型可以表示每个信号的“有效”或“无效”状态
    // 1.1初始化
    sigemptyset(&block);
    sigemptyset(&oblock);
    sigemptyset(&pending);
    // 1.2添加要屏蔽的信号
    //sigaddset(&block,BLOCK_SIGNAL);
    for(const auto signo : sigarr)
    {
        sigaddset(&block,signo);
    }
    // 1.3开始屏蔽
    sigprocmask(SIG_SETMASK,&block,&oblock);

    // 2.遍历打印pending信号集
    int cnt = 10;
    while(true)
    {
        // 2.1 初始化
        sigemptyset(&pending);
        // 2.2 获取它
        sigpending(&pending);
        // 2.3 打印它
        show_pending(pending);
        // 3 慢一点
        sleep(1);
        if(cnt-- == 0)
        {
            sigprocmask(SIG_SETMASK,&oblock,&block);// 一旦对特定信号进行接触屏蔽，一般OS要至少立马递达一个信号！
            //我当前的状态在内核态，OS顺手就把这信号递达了
            // 如果我就是要见到屏蔽信号由1置0，可以对该屏蔽信号捕捉
            cout << "恢复对信号的屏蔽，不屏蔽任何信号\n";
        }
    }
}



///////////////////////////////////////////////////////调用接口////////////////////////////////////////////////////////////////


// #include <signal.h>
// int sigemptyset(sigset_t *set);                    初始化
// int sigfillset(sigset_t *set);
// int sigaddset (sigset_t *set, int signo);          添加要屏蔽的信号
// int sigdelset(sigset_t *set, int signo);
// int sigismember（const sigset_t *set, int signo);  这个信号是否被设置了，1：是 0：否
// 函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有效信号。
// 函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系统支持的所有信号。
// 注意,在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。
// 初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号。
// 这四个函数都是成功返回0,出错返回-1。sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种 信号,若包含则返回1,不包含则返回0,出错返回-1。


// 调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。
// #include <signal.h>
// int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 
// 返回值:若成功则为0,若出错则为-1 

// how：
// SIG_BLOCK      set包含了我们希望添加到当前信号屏蔽字的信号，相当Fmask=mask|set
// SIG_UNBLOCK    set包含了我们希望从当前信号屏蔽字中解除阻塞的信号，相当mask=mask&~set
// SIG_SETMASK    设置当前信号屏蔽字为set所指向的值，相当于mask=set


// #include <signal.h>
// sigpending
// 读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。
